/*
 * Copyright 2016-2021 Pnoker. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xj.business.simulate.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ie.api.center.manager.feign.DeviceClient;
import com.ie.api.center.manager.feign.DriverClient;
import com.ie.api.center.manager.feign.PointClient;
import com.ie.api.center.manager.feign.TenantClient;
import com.xj.business.simulate.bean.model.ModelContent;
import com.xj.business.simulate.bean.model.ModelData;
import com.xj.business.simulate.service.DriverService;
import com.xj.business.simulate.service.ModelScheduleService;
import com.xj.business.simulate.service.PointValueService;
import com.xj.business.simulate.service.SimulateService;
import com.xj.business.simulate.service.job.ModelScheduleJob;
import com.xj.business.simulate.util.RandomwUtil;
import com.xj.common.bean.constant.Common;
import com.xj.common.bean.point.PointValue;
import com.xj.common.exception.ServiceException;
import com.xj.common.model.Device;
import com.xj.common.model.Driver;
import com.xj.common.model.Point;
import com.xj.common.model.Tenant;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 模型数据初始化，这里设置定时器进行模型固定时间的更新
 */
@Slf4j
@Service
public class SimulateServiceImpl implements SimulateService {


    @Resource
    ModelContent modelContent;

    @Resource
    PointValueService pointValueService;

    @Resource
    DriverService driverService;

    /**
     * 模拟某个租户下的所有实时状态上送
     * @param tenantId
     */
    @Override
    public void tenantSimulate(Long tenantId) {
        Map<Long ,List<Point>> points = modelContent.getPointMapByTenantid(tenantId);
        if(points==null ||points.size()<=0)
            return ;
        for(Long deviceid : points.keySet()){
            List<Point> pointList = points.get(deviceid);
            for (Point point: pointList){
                pointSimulate(deviceid,point);
            }
        }
    }

    /**
     * 驱动id模拟元，模拟某个驱动下的所有数据实时上送
     * @param driverId
     */
    @Override
    public void driverSimulate(Long driverId) {
        Map<Long ,List<Point>> points = modelContent.getPointMapByDriverid(driverId);
        for(Long deviceid : points.keySet()){
            List<Point> pointList = points.get(deviceid);
            for (Point point: pointList){
                pointSimulate(deviceid,point);
            }
        }
    }

    /**
     * 设备模拟源
     * @param deviceId
     */
    @Override
    public void deviceSimulate(Long deviceId) {
        for (Point point: modelContent.getModelData().getPoints().get(deviceId)){
            pointSimulate(deviceId,point);
        }
    }

    /**
     * 点数据模拟源
     * @param deviceId
     * @param point
     */
    @Override
    public void pointSimulate(Long deviceId,Point point) {
        Object value ;
        switch (point.getType()) {
            case Common.ValueType.STRING:
                value = RandomwUtil.getRandowmNum(point.getMinimum(), point.getMaximum())+"";
                break;
            case Common.ValueType.BYTE:
            case Common.ValueType.SHORT:
                value = (short)RandomwUtil.getRandowmNum(point.getMinimum(), point.getMaximum());
                break;
            case Common.ValueType.INT:
                value = RandomwUtil.getRandowmNum(point.getMinimum(), point.getMaximum());
                break;
            case Common.ValueType.LONG:
                value = (long)RandomwUtil.getRandowmNum(point.getMinimum(), point.getMaximum());
                break;
            case Common.ValueType.DOUBLE:
                value = RandomwUtil.getRandowmNum(point.getMinimum(), point.getMaximum());
                break;
            case Common.ValueType.FLOAT:
                value = (Float)RandomwUtil.getRandowmNum(point.getMinimum(), point.getMaximum());
                break;
            case Common.ValueType.BOOLEAN:
                value = RandomwUtil.random.nextBoolean();
                break;
            default:
                throw new ServiceException("Invalid device({}) point({}) value({}) type: {} ", deviceId, point.getId(), point.getType());
        }
        PointValue pv = pointValueService.getPointValue(
                deviceId, point.getId(), value,false,point.getUnit(), point.getRw()
        );
        driverService.pointValueSender(pv);
    }

    /**
     * 点数据模拟源
     * @param deviceId
     * @param points
     */
    @Override
    public void pointsSimulate(Long deviceId,List<Point> points) {
        if(deviceId!=null && points!=null && points.size()>0){
            for(Point point : points){
                pointSimulate(deviceId,point);
            }
        }
    }
}
